#Addybot Take 3 - Code Rewrite for improvement and readerabitly
package main;

use warnings;
use strict;

our $VERSION = '0.0.33';
$MyPackage::VERSION = '0.0.33';
use vars qw($VERSION);

use POE;
use POE qw(Component::IRC::State Component::IRC::Plugin::Connector Component::RSSAggregator Component::LaDBI);
use Cmdquenue;

##########################################################################
###########################    CONFIGURATION    ##########################
##########################################################################

my $mynick = 'AddyBot';
my $server = 'irc.coldfront.net';
my $port = 6667;
my $username = 'Addybot';
my $ircname ='Adam Munday: ad@vr-networks.co.uk';
my $defaultchannel = '#AddyBotTesting'; #Channel to join on first start up

### Database ###
my $dsn = 'DBI:mysql:dbname=ircbot;host=localhost';
my $db_username = 'ircbot';
my $db_password = 'botpass';

### RSS ###
my @defaultfeeds =
(
  {
    url   => 'http://www.burningsea.com/news/rss.php',#http://www.flyinglab.com/pirates/rss.php    #http://www.burningsea.com/news/rss.php
    name  => 'PotBS',
    delay => 60,
  },
);

#Set level of debug
#0 - Chat
#1 - Errors
#2 - Infomations
# For example, 1, 0, 1 = Means only show Chat and informations debugs
my @debug = (1, 1, 1);

##########################################################################
###########################    DATA CONTROL    ###########################
##########################################################################
my $pingdelay = 120;
my $myfeed; #To carry our RSS object
my $firstrun=1; #Allow RSS to run thou once without reporting the news. (On first run, it thinks all RSS entries is new)
my %channelslist; # Hold a list of channels the bot has been asked to join
my $currentnick=$mynick; #Sometimes our nick is different to assigned nick (e.g our nick already exists because it hasn't timedout yet)
my $our_dbh_id; #Database ID Handle
my $cmdquenue; #For Command quenue object
#flood control
my %floodtime;
my %floodnick;

#Commands stuff~!
my $commands =
{
   'quit'    => [2, \&irc_command_quit, 'Quit [msg] - Shuts me down. =('],
   'news'    => [0, \&irc_command_news, 'News [number] - !news report latests news from the RSS. Use !news [number] to select a previous headline. Example !news 3'],
   'join'    => [1, \&irc_command_join, 'Join (Channel) - Requires a channel argument. Example: !join #burningsea'],
   'leave'   => [1, \&irc_command_leave, 'Leave [channel] - !leave without a channel argument will cause me to leave current channel.'],
   'debug'   => [3, \&irc_command_debug, 'debug - Turn On/Off Debug Logging.'],
   'help'    => [0, \&irc_command_help, 'help - list available commands'],
   'version' => [0, \&irc_command_vers, 'version - My Current Version'],
};

##########################################################################
###########################    SETUP SESSION    ##########################
##########################################################################

#New PoCo-IRC Object and component
my $irc = POE::Component::IRC::State->spawn
(
    alias   => 'IRC',
    nick    => $mynick,
    server  => $server,
    port    => $port,
    ircname => $ircname,
    NoDNS   => 1, #Seems to cause problems. Bug with the PoCo:Client:DNS

) or die("Error: $!");

#Database Object
POE::Component::LaDBI->create(Alias => 'db')
    or die "Failed to create a POE::Component::LaDBI session\n";

#Create Session
POE::Session->create
(
    inline_states => 
    {
        #POE Events
        _start            => \&start,
        irc_start         => \&irc_start,
        _default          => \&handle_default,

        #IRC Events
        irc_registered    => \&irc_registered,
        irc_public        => \&irc_public,
        irc_msg           => \&irc_msg,
        irc_ping          => \&irc_ping,
        irc_quit          => \&irc_quit,
        irc_join          => \&irc_join,
        irc_part          => \&irc_part,
        irc_ctcp_action   => \&irc_action,
        irc_notice        => \&irc_notice,

        #Channel State
        irc_chan_sync     => \&irc_chan,

        #IRC Numbered Events
        irc_001           => \&irc_connected,
        irc_372           => \&irc_MOTD,
        irc_376           => \&irc_MOTDEnd,
        irc_433           => \&irc_nickinuse,

        #RSS Events
        handle_feed       => \&rss_feed,

        #Database Events
        connect_success    => \&db_connect_success,
        connect_failure    => \&db_connect_error,
        reconnect_success    => \&db_reconnect_success,
        reconnect_failure    => \&db_error,
        db_getnick_success => \&db_getnick_results,
        db_getnick_failure => \&db_error,
        db_offline         => \&db_offline,
        
        #Commands
        command_added     => \&command_run,
        nick_approved      => \&command_run,
        nick_unapproved    => \&command_run,

    },
    heap => { irc => $irc },
);

$poe_kernel->run();

##########################################################################
###########################    IRC EVENTS SUB    #########################
##########################################################################

sub start
{
    my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
    #Reform any startup checks
    $kernel->call('db' => 'register', OfflineEvent => 'db_offline');
    $kernel->post('db' => 'connect',
        SuccessEvent => "connect_success",
        FailureEvent => "connect_failure",
        Args         => [$dsn,$db_username,$db_password],
    );
}

#Start IRC
sub irc_start
{
    my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];

    #Get IRC Stuff
    #my $irc = $heap->{irc};
    $kernel->signal( $kernel, 'POCOIRC_REGISTER', $session->ID(), 'all' );

    #Set up Connector Plugin - It'll make sure we'll stay connected
    $heap->{connector} = POE::Component::IRC::Plugin::Connector->new(delay => $pingdelay);
    $irc->plugin_add('Connector' => $heap->{connector} );

    #Set up RSS feeds
    $heap->{'RSS'} = POE::Component::RSSAggregator->new
    (
        alias    => 'RSS',
        debug    => 0,
        callback => $session->postback("handle_feed"),
        #tmpdir   => '/tmp',        # optional caching
    );

    #Start DB Connections


    $cmdquenue = Cmdquenue->new
    (
        kernel => $kernel,
        dbalias => 'db',
    );

    return 1;
}

# We'll get one of these from each PoCo-IRC that we spawned above.
sub irc_registered
{
    my ($kernel,$heap,$sender,$irc_object) = @_[KERNEL,HEAP,SENDER,ARG0];
    my $alias = $irc_object->session_alias();

    # In any irc_* events SENDER will be the PoCo-IRC session
    $kernel->post( $sender, 'connect');

    _debug ("irc_registered: Connecting", [2]);

    return 1;
}

sub irc_connected
{
    my ($kernel,$sender) = @_[KERNEL,SENDER];

    # Get the component's object at any time by accessing the heap of
    # the SENDER
    my $poco_object = $sender->get_heap();
    _debug ('Connected: '. $poco_object->server_name(), [1]);

    #Start the RSS Feed
    $kernel->post( RSS => 'add_feed', $_ ) for @defaultfeeds;

    return 1;
}

sub irc_ping
{
    my ($kernel, $heap, $sender ) = @_[ KERNEL, HEAP, SENDER ];
    #Didn't want this to show up in debug caught by the unhandled events
    #Useless info. Just server pinging us asking if we're still alive.
    #print "ping! PONG! \n";  #Debug

    return 1;
}

sub irc_nickinuse
{
    my ($kernel, $sender ) = @_[ KERNEL, SENDER ];
    #My nick is taken, this usually means because old nick haven't timed out yet
    #Two ways of doing this, wait until old nick disconnect then take over
    #Or use NickServ ghost function, only works if IRC server has Nickserv with ghost function
    #I want to provide both, if I am registered, I wanna ghost.
    $currentnick = "$mynick" . int(rand(10));
    $kernel->post($sender => nick => "$currentnick");

    return 1;
}

sub irc_MOTD
{
    #Clean up the MOTD, Only want the $msg
    my ($kernel, $where, $msg) = @_[KERNEL, ARG0, ARG1];
    _debug("MOTD: $msg", [2]);

    return 1;
}

sub irc_MOTDEnd
{
    #Best time to join channels, nickserv identify, etc
    my ($kernel, $sender, $where, $msg) = @_[KERNEL, SENDER, ARG0, ARG1];

    #Debug
    _debug ("MOTD: $msg", [2]);
    #Join Channel
    if (scalar %channelslist > 0)
    {
        foreach my $channel (keys %channelslist)
        {
            $kernel->post($sender, 'join', $channel);
        }
    } else
    {
        $kernel->post($sender, 'join', $defaultchannel);
    }

    #Each time this comes up, it usally means we've connected/reconnected. So this is the best thing to reset with
    $cmdquenue->resetapprovednick();

    return 1;
}

sub irc_quit
{
  #So we can look out for our own nick and change back if we see it go
  my ($kernel, $sender, $who, $msg) = @_[KERNEL, SENDER, ARG0, ARG1];
  my $nick = GetNick($who);
  _debug( "Quit: $nick -> $msg", [0]);

  if ($nick eq $mynick)
  {
     $kernel->post( $sender, 'nick', $mynick);
     $currentnick = $mynick;
  } else {
      $cmdquenue->removedapprovednick($nick);
  }

  return 1;

}
sub irc_chan
{
  my ($kernel, $heap, $sender) = @_[KERNEL, HEAP, SENDER];
  %channelslist = %{ $heap->{irc}->channels() };
  return 1;
}

sub irc_join
{
  #So we can look out for our own nick and change back if we see it go
  my ($kernel, $heap, $sender, $who, $msg) = @_[KERNEL, HEAP, SENDER, ARG0, ARG1];
  my $nick = GetNick($who);
  _debug("Join: $nick -> $msg", [0]);

  return 1;

}

sub irc_part
{
  #So we can look out for our own nick and change back if we see it go
  my ($kernel, $heap, $sender, $who, $msg) = @_[KERNEL, HEAP, SENDER, ARG0, ARG1];
  my $nick = GetNick($who);
  _debug("Part: $nick -> $msg", [0]);

  if ($nick eq $currentnick)
  {
      %channelslist = %{ $heap->{irc}->channels() };
      $cmdquenue->resetapprovednick();
  } else {
      $cmdquenue->removedapprovednick($nick)
  }

  return 1;
}

sub irc_notice
{
my ($kernel, $heap, $who, @recip) = @_[KERNEL, HEAP, ARG0, ARG1, ARG2];
my $nick = GetNick($who);
my $nickname;
my $nickstatus;
my $msg = $recip[1];
my $where = $recip[0];

_debug("Notice: $who -> " . join(", ", @{$where}) . " -> $msg", [2]);
if ($nick eq 'NickServ')
  {
    if($msg =~ m/^STATUS/)
    {
      #remove STATUS and number for nick
      $nickname = substr($msg, 7, - 2);
      #get just the status
      $nickstatus = substr($msg, - 1);
      #Check status, if 3
      #print "$nickname -> $nickstatus \n";
      if ($nickstatus == 3)
      {
          $cmdquenue->addapprovednick($nickname);
      } elsif ( $nickstatus == 1 )
      {
          $kernel->post('IRC', 'privmsg', $nickname, "This commands reqires you to be logged in with Nickserv.");
          $cmdquenue->unapprovednick($nickname);
      } elsif ( $nickstatus == 2 )
      {
          $kernel->post('IRC', 'privmsg', $nickname, "This commands reqires you to be logged in with Nickserv.");
          $kernel->post('IRC', 'privmsg', $nickname, "Use /ns identify <password> to log in with this nick");
          $cmdquenue->unapprovednick($nickname);
      }
    }
  }
}


##########################################################################
###########################    IRC MSG   #################################
##########################################################################

sub irc_msg
{
  my ($kernel, $sender, $who, $something, $msg) = @_[KERNEL, SENDER, ARG0, ARG1, ARG2];
  my $nick = GetNick($who);
  my $host = GetHName($who);

  _debug("Msg: $nick -> $host -> $msg", [0]);
  irc_cmd($kernel, $sender, $msg, $nick, $nick);

  return 1;

}

sub irc_public
{
    #Whenever I get channel messages
    my ($kernel, $sender, $who, $where, $msg) = @_[KERNEL, SENDER, ARG0, ARG1, ARG2];
    my $channel = $where->[0];
    my $nick = GetNick($who);

    #Debug, I want to see what people are saying.
    _debug("Public: $nick -> $channel -> $msg", [0]);

    #If first character is ! then it's a command
    if($msg =~ m/^!/)
    {
        irc_cmd($kernel,$sender, $msg, $nick, $channel);
    }

    return 1;
}

sub irc_action
{
    my ($kernel, $sender, $who, $where, $msg) = @_[KERNEL, SENDER, ARG0, ARG1, ARG2];
    my $nick = GetNick($who);
    my $channel = $where->[0];

    #Debug, I want to see what people are doing.
    _debug("Action: $nick -> $channel -> $msg", [0]);

    return 1;

}
##########################################################################
###########################    DB SUB    #################################
##########################################################################

sub db_offline
{
    my ($kernel,$heap,$sender,$arg1, $arg2, $arg3) = @_[KERNEL,HEAP,SENDER,ARG0, ARG1, ARG2];

    _debug("db_offline: $arg1, $arg2, $arg3", [1,2]);

    if ($arg1 eq 'run_error')
    {
        POE::Component::LaDBI->create(Alias => 'db')
            or die "Failed to create a POE::Component::LaDBI session\n";

        $kernel->post('db' => 'connect',
            SuccessEvent => "reconnect_success",
            FailureEvent => "reconnect_failure",
            Args         => [$dsn,$db_username,$db_password],
        );
    }
}

sub db_connect_success
{
    my ($kernel,$heap,$sender,$dbh_id, $datatype, $data) = @_[KERNEL,HEAP,SENDER,ARG0, ARG1, ARG2];

    $dbh_id = "''" unless(defined $dbh_id);
    $datatype = "''" unless(defined $datatype);
    $data = "''" unless(defined $data);

    _debug("connect_success: $dbh_id, $datatype, $data", [1,2]);

    #Get Nicks and store
    db_getnicks($kernel, $dbh_id);
    $our_dbh_id = $dbh_id;

    #Start up the rest of the bot
    $kernel->yield('irc_start');

    return;
}

sub db_error
{
    my ($kernel,$heap, $sender, $dbh_id, $errtype, $errstr, $err) = @_[KERNEL,HEAP,SENDER,ARG0, ARG1, ARG2, ARG3];

    if ($errtype eq "ERROR")
    {
        _debug("db_error:dbh_id => $dbh_id, err_type => $errtype, errstr => $errstr, err => $err", [1]);
    } else {
        _debug("db_error:dbh_id => $dbh_id, err_type => $errtype, errstr => $errstr, err => $err", [1]);
    }

    return;
}

#DB Queries
sub db_getnicks
{
    my ($kernel, $dbh_id) = @_;

    my $sql = 'SELECT * FROM accesslist';
    $kernel->post
    (
        'db'         => 'selectall',
        SuccessEvent => 'db_getnick_success',
        FailureEvent => 'db_getnick_failure',
        HandleID     => $dbh_id,
        Args         => [$sql],
    );


    return;
}

sub db_getnick_results
{
    my ($dbh_id, $datatype, $data) = @_[ARG0..ARG2];
    my %db_nicklist;
    for my $row ( @$data )
    {
        my ($id, $nick, $lvl) = @$row;
        $db_nicklist{$nick} = $lvl;
    }

    $cmdquenue->dbrefresh(\%db_nicklist);
}

sub db_reconnect_success
{
     my ($kernel,$heap,$sender,$dbh_id, $datatype, $data) = @_[KERNEL,HEAP,SENDER,ARG0, ARG1, ARG2];
    _debug("reconnect_success: $dbh_id", [1, 2]);

}

sub db_connect_error
{
    my ($kernel,$heap, $sender, $dbh_id, $errtype, $errstr, $err) = @_[KERNEL,HEAP,SENDER,ARG0, ARG1, ARG2, ARG3];

    if ($errtype eq "ERROR")
    {
        _debug("db_error:dbh_id => $dbh_id, err_type => $errtype, errstr => $errstr, err => $err", [1]);
    } else {
        _debug("db_error:dbh_id => $dbh_id, err_type => $errtype, errstr => $errstr", [1]);
    }

    $kernel->post( 'db' => 'shutdown');
    _debug("No Database: Shutting down", [0,1,2]);
}
##########################################################################
###########################    MISC SUB    ###############################
##########################################################################

sub GetNick
{
     #Take nick!hostname and get just the nickname from it.
     my $who = shift;
     my ($name,$hostname)=split (/\!/,$who,2);

     return $name;
}

sub GetHName
{
     #Take nick!hostname and get just the hostname from it.
     my $who = shift;
     my ($name,$hostname)=split (/\!/,$who,2);

     return $hostname;
}

sub rss_feed
{
    my ($kernel, $heap, $feed ) = ( $_[KERNEL],$_[HEAP], $_[ARG1]->[0] );
    $myfeed = $feed;
    my $name = $feed->name();
    #print "RSS Name: $name \n";

    for my $headline ( $feed->late_breaking_news )
    {
        # do stuff with the XML::RSS::Headline object

        #If it's the first time this is running, ignore. It's old news we just gained. To avoid spamming the channel
        if ($firstrun == 0)
        {
            #For Each Channel we're in, we'll post theses news!
            foreach my $channel ( keys %{ $irc->channels() } ) 
            {
                $kernel->post('IRC', 'privmsg', $channel, 'New News Headline: ' . $headline->headline . " -> " . $headline->url);
                _debug('New News Headline -> ' . $headline->headline . ' -> ' . $headline->url, [2]);
            }
        }
        #$kernel->post('IRC', 'privmsg', $channel, $headline->headline . " link: " . $headline->url);
        #Think about adding new commands to deal with rss feeds. Might be fun to add new RSS from fansites
    }
    $firstrun = 0;

    return 1;
}

#Unhandled events
# Report Any Events that is currently unhandled. Gotta know what's happening
sub handle_default {

    my ($event, $args) = @_[ARG0 .. $#_];
    my @output = ( "$event: " );

    foreach my $arg ( @{$args} )
    {
        if ( ref($arg) eq 'ARRAY' ) 
        {
            push( @output, '[' . join(' ,', @{$arg} ) . ']' );
        } else {
            if (defined $args && ! $arg eq '' )
            {
				push ( @output, "'$arg'" );
            } else {
				push ( @output, "''" );
            }
        }
    }
    _debug (join (' ', @output,), [1,2]);

    return 1;
}

sub _debug
{
    #Info
    my $info = shift;

    #Debug level
    my $debuglvl = shift;

    my $debugset = 0;

    #Time
    my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
    my @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
    my($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
    my $year = 1900 + $yearOffset;
    my $theTime = "$month/$dayOfMonth/$year $hour:$minute:$second";

    #Logging
    foreach my $i (@{$debuglvl})
    {
        $debugset = 1 if ($debug[$i] == 1);
    }

    if ($debugset == 1)
    {
        print  "$theTime:$info\n";
    }
}

##########################################################################
#########################    IRC COMMANDS SUB    #########################
##########################################################################
sub irc_flood_check
{
    my ($kernel, $nick, $where, $cmd, $time) = @_;
    my $flooddrop = 0; #1 = Flooding

    if (defined $floodtime{$where})
    {
        #Ignore any commands that is less then one second
        if ($floodtime{$where}->[0] == $time)
        {
           #_debug ("Floodtime: $floodtime{$where}->[0] @ $where : $floodtime{$where}->[1] @ $cmd -> CurrentTime: $time",[1]);
           $flooddrop = 1;
        } else
        {
            if (($floodtime{$where}->[0] + 5) > $time and $floodtime{$where}->[1] eq $cmd)
            {
                #_debug ("Floodtime: $floodtime{$where}->[0] @ $where : $floodtime{$where}->[1] @ $cmd -> CurrentTime: $time",[1]);
                #$floodtime{$where} = $time;
                $flooddrop = 1;
            } else {
                #_debug ("Floodtime: $floodtime{$where}->[0] @ $where : $floodtime{$where}->[1] @ $cmd -> CurrentTime: $time",[1]);
                $floodtime{$where} = [$time,$cmd];
                $flooddrop = 0;
            }
        }

    } else {
        $floodtime{$where} = [$time,$cmd];
        #_debug ("Floodtime: $floodtime{$where} @ $where");
        $flooddrop = 0;
    }

    #Now we'll check to see if the flood is from one nick.
    #Regardless of channel.
    if (defined $floodnick{$nick})
    {
        #See if the nick has done greater then 10 commands
        #Then test to see if the 5 commands was reached in a certain limit
        if (scalar ( @{$floodnick{$nick}} ) < 10)
        {
            unshift @{$floodnick{$nick}}, $time;
        } else {
            #Yes, check to see how short the gap between first and last command
            pop @{$floodnick{$nick}};
            unshift @{$floodnick{$nick}}, $time;


            my $timedif = $floodnick{$nick}->[0] - $floodnick{$nick}->[9];
            if ($timedif < 6)
            {
                nickban($kernel, $nick); #ban0zr!
            }
            _debug( "Flood - $nick: $floodnick{$nick}->[0] - $floodnick{$nick}->[9] = Time Dif: $timedif", [2]);
        }

        #print "Floodnick: $nick -> $floodnick{$nick}->[0] \n";
    } else {
        #We'll store the last 10 times
        $floodnick{$nick} = [$time];
    }

    #Return status
    return $flooddrop;
}

sub irc_cmd
{
    #This sub is for checking for a number of things. 1 if the command exisit 2. checking that the command isn't flooding
    #Then adds command to the queue.
    my ($kernel, $sender, $cmd, $nick, $where) = @_;
    my $arg;

    #Flooding check
    my $time = time();


    #Accepted Commands
    #sort out input
    if ($cmd =~ m/ /)
    {
        ($cmd, $arg)= split(q{ },$cmd, 2);
    }
    if($cmd =~ m/^!/)
    {
        $cmd = substr($cmd, 1);
    }

    #Added to CmdQuenue
    unless(exists $commands->{$cmd})
    {
		return;
    }

    if (irc_flood_check($kernel, $nick, $where, $cmd, $time) == 1)
    {
        #Flood ineffect, dropping command.
        _debug('Command Dropped Due to Flooding',[2]);
        return;
    }
    
    if (defined $arg)
    {
        _debug( "Command: $cmd: $arg -> $nick -> $where",[2]);
    } else {
        _debug("Command: $cmd -> $nick -> $where", [2]);
    }

	$cmdquenue->addcommand
	(
		{
			command =>$cmd,
			level   =>$commands->{$cmd}->[0],
			where   =>$where,
			nick    =>$nick,
			args    =>$arg,
		}
	);



    return 1;
}

sub command_run
{
    my ($kernel, $heap, $cmdobj ) = @_[KERNEL, HEAP, ARG0];

    my $endquenue = $cmdobj->endofquenue();
    while ($endquenue == 0)
    {
        my $ready = $cmdobj->ready();
        my $cmd   = $cmdobj->command();
        my $nick  = $cmdobj->nick();
        my $args  = $cmdobj->args();
        my $where = $cmdobj->where();
        if ($ready == 1)
        {
            $commands->{$cmd}->[1]->($kernel, 'IRC', $nick , $where, $args);
            $cmdobj->cmddone();
            if (defined $args)
            {
                _debug("Commands: $cmd -> Nick: $nick -> Where: $where -> Args: $args", [2]);
            } else {
                _debug("Commands: $cmd -> Nick: $nick -> Where: $where -> Args: -", [2]);
            }
        } elsif ($ready == -1)
        {
            $kernel->post(IRC=> 'privmsg', $nick, "You do not have permission to run $cmd");
            _debug("Commands: " . $cmd . " dropped", [2]);
            $cmdobj->cmddone();
        } elsif ($ready == 0)
        {
            _debug("Commands: " . $cmd . " ignored - loop exited",[2]);
            last;
        }
        $endquenue = $cmdobj->endofquenue();
    }

    return;
}

sub nickban
{
    my ($kernel, $nick)= @_;
    #_debug("Nick banned: $nick");
    #$kernel->post(IRC=> 'privmsg', $nick, 'Shut the f**k up, spammer');


}
##########################################################################
###########################    IRC COMMANDS SUB    #######################
##########################################################################

sub irc_command_quit
{
    my($kernel, $sender, $nick, $where, $arg) = @_;
    my $quitmsg;

    if(defined $arg)
    {
        $quitmsg = $arg;
    } else {
        $quitmsg = 'Hi-jacked by Pirates.';
    }

    $kernel->post($sender => 'quit', $quitmsg);
    $kernel->post( RSS => 'shutdown');
    $kernel->signal( $sender, 'POCOIRC_SHUTDOWN');
    #$kernel->post( db => 'disconnect', SuccessEvent => "db_shutdown", FailureEvent => 'dberror', HandleId => $our_dbh_id);
    $kernel->post( db => 'shutdown');
    _debug("Shutdown",[0,1,2]);

    return 1;
}

sub irc_command_news
{
    my($kernel, $sender, $nick, $where, $arg) = @_;

    if (! defined $myfeed)
    {
        #No feeds, usually due to delay in fetching RSS feed.
        $kernel->post(IRC=> 'privmsg', $where, 'Error: I\'ve not got the feed yet. Try again in 30 seconds.');
        _debug("Error: I've not got the feed yet", [1,2]);
        return;
    }

    my @headlines = $myfeed->headlines;
    my $noheadlines = (scalar @headlines);

    if(defined $arg)
    {
        #We have a Arg, if it's valid report the selected news
        if ($arg !~ m/\D/ && $arg > 0  && $arg < $noheadlines + 1)
        {
            $kernel->post(IRC=> 'privmsg', $where, 'News ' . int($arg) . ': ' . $headlines[$arg - 1]->headline . ' -> ' . $headlines[$arg - 1]->url);
            _debug('News: ' . $headlines[$arg - 1]->headline . ' -> ' . $headlines[$arg - 1]->url, [0,2]);
        } else {
            #Duh! Invalid arguments
            $kernel->post(IRC=> 'privmsg', $where, "There are only $noheadlines - Please use !news [1-$noheadlines] to select the headlines");
        }
    } else {
        #Report the latests news
        $kernel->post(IRC=> 'privmsg', $where, 'Latest News: ' . $headlines[0]->headline . ' -> ' . $headlines[0]->url);
        _debug('Latest: ' . $headlines[0]->headline . ' -> ' . $headlines[0]->url, [0,2]);
    }

    return;
}


sub irc_command_join
{
    my($kernel, $sender, $nick, $where, $arg) = @_;
    
    if(defined $arg)
    {
        #Test $arg for correct syntax. - TO DO
        my @arg = split(' ',$arg);
        $kernel->post(IRC=> 'join', $arg[0]);
    } else {
        #incorrect syntax
    }

    return 1;
}

sub irc_command_leave
{
    my($kernel, $sender, $nick, $where, $arg) = @_;

    if(defined $arg)
    {
        #Test $arg for correct syntax. -TO DO
        my @arg = split(' ',$arg);
        $kernel->post(IRC=> 'part', $arg[0]);
    } else {
        #Leave current Channel, if it's not a nick
        unless ($nick eq $where)
        {
            $kernel->post(IRC=> 'part', $where);
        }
    }
    
    return 1;
}

sub irc_command_debug
{
    my($kernel, $sender, $nick, $where, $arg) = @_;
    #Only send send a privmsg to calling user.
    #At the moment, it is consoel output.
    #This will handle debug logging and so on.

    unless(defined $arg or $arg eq '')
    {
        $kernel->post(IRC=> 'privmsg', $nick, 'Incorrect Syntax for debug. Requires argugments');
        _debug("Debug: undefined args",[1,2]);
        return;
    }
    my @debugarg = split(',', $arg);

    if((scalar @debugarg) != 3)
    {
        $kernel->post(IRC=> 'privmsg', $nick, 'Incorrect Syntax for debug');
        _debug("Debug: incorrect args: $arg",[1,2]);
        return;
    }
    
    @debug = @debugarg;

    return;

}

sub irc_command_help
{
    my($kernel, $sender, $nick, $where, $arg) = @_;

    my $listofcommand;

    #Clearing "!"
    if($arg =~ m/^!/)
    {
        $arg = substr($arg, 1);
    }

    if(defined $arg)
    {
        if (exists $commands->{$arg})
        {
            #Print Help on this command
            $kernel->post(IRC => 'privmsg', $where, $commands->{$arg}->[2]);
        } else {
            #Command does not exists
            $kernel->post(IRC => 'privmsg', $where, 'This command does not exists');
        }
    } else {
        #List Commands
        for (keys %{$commands})
        {
            $listofcommand = $listofcommand . $_ . ", ";
        }
        $kernel->post(IRC=> 'privmsg', $where, "What commands would you like help with? (Example !help help) $listofcommand");

    }

}

sub irc_command_vers
{
    my($kernel, $sender, $nick, $where, $arg) = @_;
    $kernel->post(IRC=> 'privmsg', $where, "My current version is: $VERSION");
}

exit 1;